using System.Collections.Generic;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using LogikBug.ModularMvc.Factories;
using LogikBug.ModularMvc.Hosting;
using LogikBug.ModularMvc.Locations;
using LogikBug.ModularMvc.Registration;

namespace LogikBug.ModularMvc
{
	public abstract class ModularMvcApplication : HttpApplication
	{
		#region Properties
		
		public ModularHttpContext ModuleContext
		{
			get
			{
				return ModularHttpContext.Current;
			}
		}

		public virtual IDependencyResolver ServiceProvider
		{
			get
			{
				return DependencyResolver.Current;
			}
		}

		public virtual IRegistrationContext RegistrationContext { get; protected set; }

		#endregion

		#region Methods

		protected virtual void RegisterIgnoreRoutes()
		{
			var routes = RegistrationContext.Routes;

			routes.IgnoreRoute("{resource}.htm");
			routes.IgnoreRoute("{resource}.html");
			routes.IgnoreRoute("{resource}.aspx");
			routes.IgnoreRoute("{resource}.cshtml");
			routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
		}

		protected virtual void Application_Start()
		{
			InitializeServiceLocator();
			
			var locator = ServiceProvider;
			RegistrationContext = locator.GetInstance<IRegistrationContext>();
			//ControllerBuilder.Current.SetControllerFactory(locator.GetInstance<IControllerFactory>());
			ModelBinders.Binders.DefaultBinder = locator.GetInstance<DynamicTypeModelBinder>();
			HostingEnvironment.RegisterVirtualPathProvider(locator.GetInstance<AssemblyResourceProvider>());

			RegisterIgnoreRoutes();
			RegisterModules();
		}

		protected abstract void InitializeServiceLocator();

		protected abstract string GetConnectionStringName();

		protected abstract void RegisterModules();

		protected virtual IEnumerable<ILocation> GetLocations()
		{
			return new[]
			{
				LocationFactory.Instance.FromCodegenDir()
			};
		}

		/// <summary>
		/// Disposes the <see cref="T:System.Web.HttpApplication"/> instance.
		/// </summary>
		public override void Dispose()
		{
			//base.Dispose();

			//var locator = ServiceLocator;

			//if (locator is IDisposable)
			//{
			//    ((IDisposable)locator).Dispose();
			//}
		}

		#endregion
	}

	public abstract class ModularMvcApplication<T> : ModularMvcApplication where T : class//, IReference, new()
	{
		#region Methods

		protected override void RegisterModules()
		{
			var locations = GetLocations();
			ModuleProvider.Current.Initialize(locations, RegistrationContext);
		}

		#endregion
	}
}